#include <Wire.h>
#include <SPI.h>
#include <Arduino.h>
#include "TouchDrvCSTXXX.hpp"
#include "pin_config.h"
#include <FS.h>
#include <SD_MMC.h>
#include <lvgl.h>
#include "SensorQMI8658.hpp"
#include "Arduino_GFX_Library.h"
#include "lv_conf.h"
#include "BOZAI.h"
#include "MIUMIU.h"
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>

// WiFi 设置
const char* ssid = "WAXD";
const char* password = "22222222";

const char* ssid_2 = "XiaomiSU7Max";
const char* password_2 = "22222222";

const char* ssid_3 = "IOV_TMN218876";
const char* password_3 = "2222222222";

const char* ssid_4 = "TP-LINK_1059";
const char* password_4 = "JzRzKa0419";


// NTP 设置
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 28800, 60000); // GMT+8, 60秒更新一次

SensorQMI8658 qmi;
IMUdata acc;
IMUdata acc_pre;
IMUdata gyr;

lv_obj_t *ball;                  // Global ball object
lv_chart_series_t *acc_series_x;  // Acceleration X series
lv_chart_series_t *acc_series_y;  // Acceleration Y series
lv_chart_series_t *acc_series_z;  // Acceleration Z series

#define EXAMPLE_LVGL_TICK_PERIOD_MS 2

TouchDrvCSTXXX touch;
int16_t x[5], y[5];

uint8_t functionId = 0;

bool isPressed = false;

uint32_t screenWidth;
uint32_t screenHeight;

static lv_disp_draw_buf_t draw_buf;


Arduino_DataBus *bus = new Arduino_ESP32QSPI(
  LCD_CS /* CS */, LCD_SCLK /* SCK */, LCD_SDIO0 /* SDIO0 */, LCD_SDIO1 /* SDIO1 */,
  LCD_SDIO2 /* SDIO2 */, LCD_SDIO3 /* SDIO3 */);

Arduino_GFX *gfx = new Arduino_CO5300(
  bus,
  LCD_RESET /* RST */,
  0 /* rotation */,
  false /* IPS */,
  LCD_WIDTH,
  LCD_HEIGHT,
  6 /* col_offset1 */,
  0 /* row_offset1 */,
  0 /* col_offset2 */,
  0 /* row_offset2 */
);
#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(const char *buf) {
  Serial.printf(buf);
  Serial.flush();
}
#endif

void example_lvgl_rounder_cb(struct _lv_disp_drv_t *disp_drv, lv_area_t *area)
{
    if(area->x1 % 2 !=0)area->x1--;
    if(area->y1 % 2 !=0)area->y1--;
    // 变为奇数(如果是偶数就加 1)
    if(area->x2 %2 ==0)area->x2++;
    if(area->y2 %2 ==0)area->y2++;
}

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

void example_increase_lvgl_tick(void *arg) {
  /* Tell LVGL how many milliseconds has elapsed */
  lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
}

static uint8_t count = 0;
void example_increase_reboot(void *arg) {
  count++;
  if (count == 30) {
    esp_restart();
  }
}

uint8_t ring_color_state = 0;

/*Read the touchpad*/
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
  static int lastX = 0;
  static int lastY = 0;
  static int functionId_Lock = 1;
  static int touch_duration_start_time = 0;
  uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint());

  if (touched > 0) {
    if(functionId_Lock == 1){
      touch_duration_start_time = millis();
    }
    functionId_Lock = 0;
    data->state = LV_INDEV_STATE_PR;  // 设置为按下状态
    data->point.x = x[0];             // 使用第一个触摸点的坐标
    data->point.y = y[0];
    Serial.print("touch_duration_start_time: ");
    Serial.println(touch_duration_start_time);
    Serial.print("X: ");
    Serial.print(data->point.x);
    Serial.print(" Y: ");
    Serial.println(data->point.y);
    lastX = int(data->point.x);
    lastY = int(data->point.y);
    if(lastY > 60 && lastY < 420 ){
      gfx->Display_Brightness(int(data->point.x / 2));//Brightness setting
    }
    
  } else {
    data->state = LV_INDEV_STATE_REL;  // 设置为释放状态
    //If touce more than 3 seconds, change ring color
    if((millis() - touch_duration_start_time)>3000){
      if(ring_color_state == 0){
        ring_color_state = 1;
      }
      else{
        ring_color_state = 0;
      }
    }
    if(functionId_Lock == 0){
      if(lastY <= 60){
        if(functionId == 0){
          functionId = 3;
        }
        else{
          functionId -= 1;
        }
      }
      else if(lastY >= 420 ){
        if(functionId == 3){
          functionId = 0;
        }
        else{
          functionId += 1;
        }
      }
      Serial.println(functionId);
      functionId_Lock = 1;
    }
  }
}

// 读文件内容 path是路径
static esp_err_t sd_read_file(const char *path, uint8_t *buffer, size_t size)
{
    // Serial.printf( "Reading file %s", path);
    FILE *f = fopen(path, "rb");  // 以只读方式打开文件
    if (f == NULL) {
        Serial.println("Failed to open file for reading");
        return ESP_FAIL;
    }
    size_t read = fread(buffer, 1, size, f);
    // Serial.println( "Successfully fread");
    fclose(f); // 关闭文件
    if (read == size) {
        // Serial.printf( "Successfully read %d bytes from %s", size, path);
    } else {
        Serial.println("Error reading file");
    }

    return ESP_OK;
}

void display_png_from_sd(const char * fullpath,unsigned int PicSize,unsigned int PixelSize,unsigned int playTime){
  unsigned long fileSize = 0;
  fileSize = PixelSize;

  unsigned char *pixels = (unsigned char *)heap_caps_malloc(fileSize, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
    if (NULL == pixels)
    {
        ESP_LOGE(TAG, "Memory for bitmap is not enough");
        return;
    }
    sd_read_file(fullpath,pixels,fileSize);

    static lv_img_dsc_t img_dsc;
    img_dsc.header.w = PicSize;
    img_dsc.header.h = PicSize;
    img_dsc.header.always_zero = 0;
    img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR; // Use RAW so LVGL handles it as-is
    img_dsc.data = pixels;
    img_dsc.data_size = fileSize;

    lv_obj_t * img = lv_img_create(lv_scr_act());
    lv_img_set_src(img, &img_dsc);
    lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);

    lv_timer_handler(); /* let the GUI do its work */
    vTaskDelay(pdMS_TO_TICKS(playTime));
    lv_obj_del(img);
    heap_caps_free(pixels);  // 释放内存
  
}

unsigned char display_gif_from_sd_running = 0;
void display_gif_from_sd(const char * fullpath,unsigned int playTime){
  display_gif_from_sd_running = 1;
  unsigned long fileSize = 0;
  File file = SD_MMC.open(fullpath + 7,FILE_READ); ///* skip "/sdcard" */
  Serial.printf("\nFile Open");
  fileSize = file.size();//Get the size of the file
  Serial.print(fileSize);
  Serial.println("Bytes");
  file.close();

  unsigned char *pixels = (unsigned char *)heap_caps_malloc(fileSize, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
    if (NULL == pixels)
    {
        ESP_LOGE(TAG, "Memory for bitmap is not enough");
        return;
    }
    sd_read_file(fullpath,pixels,fileSize);

    static lv_img_dsc_t gif_dsc;
    gif_dsc.header.w = 480;
    gif_dsc.header.h = 480;
    gif_dsc.header.always_zero = 0;
    gif_dsc.header.cf = LV_IMG_CF_RAW; // Use RAW so LVGL handles it as-is
    gif_dsc.data = pixels;
    gif_dsc.data_size = fileSize;

    lv_obj_t * gif = lv_gif_create(lv_scr_act());
    lv_gif_set_src(gif, &gif_dsc);
    lv_obj_align(gif, LV_ALIGN_CENTER, -20, -20);
    display_gif_from_sd_running = 0;
    for(int i = 0; i < playTime;i++){
        lv_timer_handler(); /* let the GUI do its work */
        delay(5);
        if(functionId != 2){
          break;
        }
    }
    // vTaskDelay(pdMS_TO_TICKS(playTime * 50));
    display_gif_from_sd_running = 1;
    lv_obj_del(gif);
    heap_caps_free(pixels);  // 释放内存
    display_gif_from_sd_running = 0;
    
}

//               ------
//            /          \
//           |    top     |  X: <-  -1  -> 1    Y:  ^ 1   V -1    Z:   -1
//            \           /
//               -------
//                  ||  

//               ------
//            /          \
//           |    bottom  |  X: <-  -1  -> 1    Y:  ^ 1   V -1    Z:   1
//            \           /
//               -------
//                  ||  

unsigned int stable_cnt = 301;
void print_Qmi_Data(void){
  if (qmi.getDataReady()) {
    if (qmi.getAccelerometer(acc.x, acc.y, acc.z)) {
      if((acc.x - acc_pre.x)<0.1 && (acc.x - acc_pre.x)>-0.1 
      && (acc.y - acc_pre.y)<0.1 && (acc.y - acc_pre.y)>-0.1
      && (acc.x > -0.2) && (acc.x < 0.2)){
        if(stable_cnt < 3000)
          stable_cnt += 1;
      }
      else{
        stable_cnt = 0;
      }
      acc.x = 0.75 * acc.x + 0.25 * acc_pre.x;
      acc.y = 0.75 * acc.y + 0.25 * acc_pre.y;
      acc.z = 0.75 * acc.z + 0.25 * acc_pre.z;
      acc_pre.x = acc.x;
      acc_pre.y = acc.y;
      acc_pre.z = acc.z;
      /*
      Serial.print("\n{ACCEL: ");
      Serial.print(acc.x);
      Serial.print(",");
      Serial.print(acc.y);
      Serial.print(",");
      Serial.print(acc.z);
      Serial.println("}");
      */
    }
  }
}

unsigned char g_hour = 0;
unsigned char g_minute = 0;
unsigned char g_second = 0;
unsigned char g_200millsecond = 0;

void TimeInit(void){
  // 连接 WiFi
  unsigned char testCnt = 0;
  Serial.println("Connecting to SU7 WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED && testCnt < 8) {
    delay(250);
    Serial.print(".");
    testCnt ++;
  }
  if(WiFi.status() != WL_CONNECTED){
    Serial.println("Connecting to Room WiFi...");
    WiFi.begin(ssid_2, password_2);
    testCnt = 0;
    while (WiFi.status() != WL_CONNECTED && testCnt < 8) {
      delay(250);
      Serial.print(".");
      testCnt ++;
    }
  }
  if(WiFi.status() != WL_CONNECTED){
    Serial.println("Connecting to Phone WiFi...");
    WiFi.begin(ssid_3, password_3);
    testCnt = 0;
    while (WiFi.status() != WL_CONNECTED && testCnt < 8) {
      delay(250);
      Serial.print(".");
      testCnt ++;
    }
  }
  if(WiFi.status() != WL_CONNECTED){
    Serial.println("Connecting to Phone WiFi...");
    WiFi.begin(ssid_4, password_4);
    testCnt = 0;
    while (WiFi.status() != WL_CONNECTED && testCnt < 8) {
      delay(250);
      Serial.print(".");
      testCnt ++;
    }
  }
  if(WiFi.status() != WL_CONNECTED){
    Serial.println("\nWiFi NOT connected");
    return;
  }
  Serial.println("\nWiFi connected");
  // 初始化 NTP
  timeClient.begin();
  testCnt = 0;
  while (!timeClient.update() && testCnt < 8) {
    delay(500);
    Serial.print(".");
    testCnt ++;
  }
  setTime(timeClient.getEpochTime());
  Serial.println("NTP time synced");
  time_t t = now();
  g_hour = hour(t);
  g_minute = minute(t);
  g_second = second(t);
  timeClient.end();
  WiFi.disconnect();
  WiFi.mode(WIFI_OFF);
}


void setup() {
  Serial.begin(115200);
  //查看ESP32堆的总共大小
  Serial.printf("ESP32 total Heap size :%d bytes\n",ESP.getHeapSize());
  //查看ESP32堆的可用大小
  Serial.printf("ESP32 free  Heap size :%d bytes\n",ESP.getFreeHeap());
  //查看ESP32的Flash的大小
  Serial.printf("Flash size: %d bytes\n", ESP.getFlashChipSize());
  //查看ESP32的内部和外部RAM的总共大小
  Serial.printf("Deafult total size: %d bytes\n", heap_caps_get_total_size(MALLOC_CAP_DEFAULT));
  //查看ESP32的内部和外部RAM的可用大小
  Serial.printf("Deafult free size: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
  //查看ESP32的内部RAM总共大小
  Serial.printf("Internal total size: %d bytes\n", heap_caps_get_total_size(MALLOC_CAP_INTERNAL));
  //查看ESP32的内部RAM可用大小
  Serial.printf("Internal free size: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
  //查看ESP32的外部RAM的可用大小
  Serial.printf("PSRAM total size: %d bytes\n", heap_caps_get_total_size(MALLOC_CAP_SPIRAM));
  //查看ESP32的外部RAM的可用大小
  Serial.printf("PSRAM free size: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
  TimeInit();
  Wire.begin(IIC_SDA, IIC_SCL);
  SD_MMC.setPins(SDMMC_CLK, SDMMC_CMD, SDMMC_DATA);
  delay(1000);
  Serial.println("\n=== LVGL SD_MMC FS Driver TEST ===");

  if (!SD_MMC.begin("/sdcard", true)) {
    Serial.println("SD_MMC mount FAILED!");
    while (1);
  }

  Serial.println("SD_MMC mounted OK!");
  // Print files for sanity check
  File root = SD_MMC.open("/");
  while (File file = root.openNextFile()) {
    Serial.printf("  %s %s %u\n",
                  file.isDirectory() ? "DIR " : "FILE",
                  file.name(),
                  file.size());
    file.close();
  }

  uint8_t address = 0x5A;

  touch.setPins(-1, 11);

  bool result = touch.begin(Wire, address, 15, 14);
  touch.setMaxCoordinates(466, 466);
  touch.setMirrorXY(true, true);
  attachInterrupt(
    11, []() {
      isPressed = true;
    },
    FALLING);
  gfx->begin(30000000);
  gfx->Display_Brightness(200);
  screenWidth = gfx->width();
  screenHeight = gfx->height();

  lv_init();
  lv_color_t *buf1 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);
  lv_color_t *buf2 = (lv_color_t *)heap_caps_malloc(screenWidth * screenHeight / 4 * sizeof(lv_color_t), MALLOC_CAP_DMA);

#if LV_USE_LOG != 0
  lv_log_register_print_cb(my_print); /* register print function for debugging */
#endif

  lv_disp_draw_buf_init(&draw_buf, buf1, buf2, screenWidth * screenHeight / 4);

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  /*Change the following line to your display resolution*/
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.rounder_cb = example_lvgl_rounder_cb;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);

  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register(&indev_drv);

  const esp_timer_create_args_t lvgl_tick_timer_args = {
    .callback = &example_increase_lvgl_tick,
    .name = "lvgl_tick"
  };

  const esp_timer_create_args_t reboot_timer_args = {
    .callback = &example_increase_reboot,
    .name = "reboot"
  };

  esp_timer_handle_t lvgl_tick_timer = NULL;
  esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer);
  esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000);

// 设置背景颜色为黑色
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x0), 0);

if (!qmi.begin(Wire, QMI8658_L_SLAVE_ADDRESS, IIC_SDA, IIC_SCL)) {
    Serial.println("Failed to find QMI8658 - check your wiring!");
    while (1) {
      delay(1000);
    }
  }
  qmi.configAccelerometer(SensorQMI8658::ACC_RANGE_4G, SensorQMI8658::ACC_ODR_1000Hz, SensorQMI8658::LPF_MODE_0);
  qmi.enableAccelerometer();
  
  xTaskCreatePinnedToCore(
                    taskLVGL,          /* 任务函数 */
                    "taskLVGL",        /* 任务名 */
                    10000,            /* 任务栈大小*/
                    NULL,             /* 参数 */
                    2,                /* 优先级Higher */
                    NULL,1);            /* 任务句柄 & Core*/

  xTaskCreatePinnedToCore(
                  taskTime,          /* Task function. */
                  "taskTime",        /* String with name of task. */
                  10000,            /* Stack size in bytes. */
                  NULL,             /* Parameter passed as input of the task */
                  2,                /* Priority of the task. */
                  NULL,0);            /* Task handle & Core. */

  xTaskCreatePinnedToCore(
                  taskQMI,          /* Task function. */
                  "taskQMI",        /* String with name of task. */
                  10000,            /* Stack size in bytes. */
                  NULL,             /* Parameter passed as input of the task */
                  1,                /* Priority of the task. */
                  NULL,0);            /* Task handle & Core. */
  while(1){
    ;
  }
  Serial.println("Setup done");
}

void loop() {
  delay(1000);
}

unsigned char displayID = 0;

#define SEAT 0
#define RUN 1
#define TURNL 2
#define TURNR 3
#define HAPPY 4
#define SAD 5
#define RELAX 6
#define SICKL 7
#define SICKR 8


void functionId_0(void){
    LV_IMG_DECLARE(ring_yellow);
    LV_IMG_DECLARE(ring_blue);
    LV_FONT_DECLARE(FontNi7seg);
    lv_obj_t * ring_bg = lv_img_create(lv_scr_act());
    if(ring_color_state == 1){
      lv_img_set_src(ring_bg, &ring_yellow);
    }
    else{
      lv_img_set_src(ring_bg, &ring_blue);
    }
    lv_obj_align(ring_bg, LV_ALIGN_CENTER, 0, 0);
    lv_obj_t * led_time_label = lv_label_create(lv_scr_act());
    lv_obj_set_style_text_font(led_time_label, &FontNi7seg, LV_PART_MAIN);
    lv_obj_set_style_text_color(led_time_label, lv_color_hex(0xFFFFFF), 0);
    lv_label_set_text_fmt(led_time_label, "%02d:%02d", g_hour, g_minute);
    //Set transform size big enough to contain rotated object
    lv_obj_set_style_transform_width(led_time_label, 100, 0);  // Adjust as needed
    lv_obj_set_style_transform_height(led_time_label, 100, 0);
    //Set pivot point to center
    lv_obj_set_style_transform_pivot_x(led_time_label, 50, 0); // Half of transform_width
    lv_obj_set_style_transform_pivot_y(led_time_label, 50, 0); // Half of transform_height
    //Rotate 90 degrees (LVGL uses 0.1° units, so 900 = 90°)
    lv_obj_set_style_transform_angle(led_time_label, 900, 0);
    lv_obj_align(led_time_label,  LV_ALIGN_CENTER, 60, -90);
    int16_t angle = 0;
    while(functionId == 0){
          // Serial.print(g_hour);
          // Serial.print(":");
          // Serial.println(g_minute);
          // Serial.print(":");
          // Serial.println(g_second);
        angle = g_200millsecond * 12 + g_second * 60 - 600;
        lv_img_set_angle(ring_bg, angle);
        lv_label_set_text_fmt(led_time_label, "%02d:%02d", g_hour, g_minute);
        lv_timer_handler(); /* let the GUI do its work */
        vTaskDelay(pdMS_TO_TICKS(10));
    }
    lv_obj_del(ring_bg);
    lv_obj_del(led_time_label);
}

void functionId_1(void){
    LV_IMG_DECLARE(ACCL_Table);
    lv_obj_t * table = lv_img_create(lv_scr_act());
    lv_img_set_src(table, &ACCL_Table);
    // lv_obj_center(table);
    lv_obj_align(table, LV_ALIGN_CENTER, 0, 0);
    /* Create a simple object for the ball */
    ball = lv_obj_create(lv_scr_act());
    lv_obj_set_size(ball, 30, 30);  // 20x20 pixels
    lv_obj_set_style_radius(ball, LV_RADIUS_CIRCLE, 0);  // Make it round
    lv_obj_set_style_bg_color(ball, lv_palette_main(LV_PALETTE_CYAN), 0);  // color
    while(functionId == 1){
      // 👇 NEW: update ball position
      int max_offset = 150;
      int x_offset = (acc.z ) * max_offset;
      int y_offset = (acc.x ) * max_offset;
      lv_obj_align(ball, LV_ALIGN_CENTER, -1 * x_offset, y_offset);
      lv_timer_handler(); /* let the GUI do its work */
      // Optional small delay to avoid hammering GIF load
      vTaskDelay(pdMS_TO_TICKS(10));
    }
    lv_obj_del(table);
    lv_obj_del(ball);
}

void functionId_2(void){

        uint32_t randomNum = 0;

        while(functionId == 2){

          while(displayID == SEAT && functionId == 2){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < SEAT_SET_NUM; setCnt++){
              if(randomNum <= miumiu_Seat_set_Probability[setCnt]){
                for(char i = 0; i < miumiu_Seat_set_size[setCnt]; i++ ){
                  display_png_from_sd(miumiu_Seat_set[setCnt][i],240,115200,25);
                  if(functionId != 2 || displayID != SEAT){
                      break;
                    }
                  }
                break;
              }
            }
          }

          while(displayID == RUN && functionId == 2){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < RUN_SET_NUM; setCnt++){
              if(randomNum <= miumiu_Run_set_Probability[setCnt]){
                for(char i = 0; i < miumiu_Run_set_size[setCnt]; i++ ){
                  display_png_from_sd(miumiu_Run_set[setCnt][i],240,115200,25);
                  if(functionId != 2 || displayID != RUN){
                      break;
                    }
                  }
                break;
              }
            }
          }

          while(displayID == TURNL && functionId == 2){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < TURNL_SET_NUM; setCnt++){
              if(randomNum <= miumiu_TurnL_set_Probability[setCnt]){
                for(char i = 0; i < miumiu_TurnL_set_size[setCnt]; i++ ){
                  display_png_from_sd(miumiu_TurnL_set[setCnt][i],240,115200,25);
                  if(functionId != 2){
                    break;
                  }
                }
                break;
              }
            }
          }

          while(displayID == TURNR && functionId == 2){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < TURNR_SET_NUM; setCnt++){
              if(randomNum <= miumiu_TurnR_set_Probability[setCnt]){
                for(char i = 0; i < miumiu_TurnR_set_size[setCnt]; i++ ){
                  display_png_from_sd(miumiu_TurnR_set[setCnt][i],240,115200,25);
                  if(functionId != 2){
                    break;
                  }
                }
                break;
              }
            }
          }

          while(displayID == HAPPY && functionId == 2){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < HAPPY_SET_NUM; setCnt++){
              if(randomNum <= miumiu_Happy_set_Probability[setCnt]){
                for(char i = 0; i < miumiu_Happy_set_size[setCnt]; i++ ){
                  display_png_from_sd(miumiu_Happy_set[setCnt][i],240,115200,25);
                  if(functionId != 2 || displayID != HAPPY){
                    break;
                  }
                }
                break;
              }
            }
          }

          while(displayID == RELAX && functionId == 2){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < RELAX_SET_NUM; setCnt++){
              if(randomNum <= miumiu_Relax_set_Probability[setCnt]){
                for(char i = 0; i < miumiu_Relax_set_size[setCnt]; i++ ){
                  display_png_from_sd(miumiu_Relax_set[setCnt][i],240,115200,25);
                  if(functionId != 2 || displayID != RELAX){
                    break;
                  }
                }
                break;
              }
            }
          }
        }
}


void functionId_3(void){
        uint32_t randomNum = 0;
        while(functionId == 3){
          while(displayID == SEAT && functionId == 3){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < BOZAI_SEAT_SET_NUM; setCnt++){
              if(randomNum <= BOZAI_Seat_set_Probability[setCnt]){
                for(char i = 0; i < BOZAI_Seat_set_size[setCnt]; i++ ){
                  display_png_from_sd(BOZAI_Seat_set[setCnt][i],240,115200,25);
                  if(functionId != 3 || displayID != SEAT){
                      break;
                    }
                  }
                break;
              }
            }
          }

          while(displayID == RUN && functionId == 3){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < BOZAI_RUN_SET_NUM; setCnt++){
              if(randomNum <= BOZAI_Run_set_Probability[setCnt]){
                for(char i = 0; i < BOZAI_Run_set_size[setCnt]; i++ ){
                  display_png_from_sd(BOZAI_Run_set[setCnt][i],240,115200,25);
                  if(functionId != 3 || displayID != RUN){
                      break;
                    }
                  }
                break;
              }
            }
          }

          while(displayID == TURNL && functionId == 3){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < TURNL_SET_NUM; setCnt++){
              if(randomNum <= BOZAI_TurnL_set_Probability[setCnt]){
                for(char i = 0; i < BOZAI_TurnL_set_size[setCnt]; i++ ){
                  display_png_from_sd(BOZAI_TurnL_set[setCnt][i],240,115200,25);
                  if(functionId != 3){
                    break;
                  }
                }
                break;
              }
            }
          }

          while(displayID == TURNR && functionId == 3){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < BOZAI_TURNR_SET_NUM; setCnt++){
              if(randomNum <= BOZAI_TurnR_set_Probability[setCnt]){
                for(char i = 0; i < BOZAI_TurnR_set_size[setCnt]; i++ ){
                  display_png_from_sd(BOZAI_TurnR_set[setCnt][i],240,115200,25);
                  if(functionId != 3){
                    break;
                  }
                }
                break;
              }
            }
          }

          while(displayID == HAPPY && functionId == 3){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < BOZAI_HAPPY_SET_NUM; setCnt++){
              if(randomNum <= BOZAI_Happy_set_Probability[setCnt]){
                for(char i = 0; i < BOZAI_Happy_set_size[setCnt]; i++ ){
                  display_png_from_sd(BOZAI_Happy_set[setCnt][i],240,115200,25);
                  if(functionId != 3 || displayID != HAPPY){
                    break;
                  }
                }
                break;
              }
            }
          }


          while(displayID == RELAX && functionId == 3){
            randomNum = random(1,100);
            for(char setCnt = 0; setCnt < BOZAI_RELAX_SET_NUM; setCnt++){
              if(randomNum <= BOZAI_Relax_set_Probability[setCnt]){
                for(char i = 0; i < BOZAI_Relax_set_size[setCnt]; i++ ){
                  display_png_from_sd(BOZAI_Relax_set[setCnt][i],240,115200,25);
                  if(functionId != 3 || displayID != RELAX){
                    break;
                  }
                }
                break;
              }
            }
          }
        }
}

void taskLVGL( void * parameter )
{
    while(1){
        if(functionId == 0){
          functionId_0();
        }
        else if(functionId == 1){
          functionId_1();
        }
        else if(functionId == 2){
          functionId_2();
        }
        else if(functionId == 3){
          functionId_3();
        }
    }
    Serial.println("Ending taskLVGL");
    vTaskDelete( NULL );
 
}


void taskQMI( void * parameter)
{
    while(1){
        print_Qmi_Data();
        if(acc.x < -0.17 && acc.x >= -0.5){
          displayID = TURNR;
        }
        else if(acc.x > 0.17 && acc.x <= 0.5){
          displayID = TURNL;
        }
        else if(acc.x < -0.5){
          // displayID = SICKR;
          displayID = TURNR;
        }
        else if(acc.x > 0.5){
          // displayID = SICKL;
          displayID = TURNL;
        }
        else{
          if(stable_cnt >100 && stable_cnt < 400){
            displayID = HAPPY;
          }
          else if((stable_cnt >=400 && stable_cnt < 1000) || (stable_cnt >= 1000 && g_hour <= 17)){
            displayID = SEAT;
          }
          else if(stable_cnt >=1000 && g_hour >17){
            displayID = RELAX;
          }
          else{
            displayID = RUN;
          }
        }
        vTaskDelay(50);
    }
    Serial.println("Ending taskQMI");
    vTaskDelete( NULL );
 
}



void taskTime( void * parameter)
{
    while(1){
        static unsigned long lastNtpUpdate = 0;
        unsigned long nowTime = millis();
        if(g_200millsecond < 5){
          g_200millsecond += 1;
        }
        if (nowTime - lastNtpUpdate >= 1000) {
          g_200millsecond = 0;
          if(g_second == 59){
            g_second = 0;
            if(g_minute == 59){
              g_minute = 0;
              if(g_hour== 23){
                g_hour = 0;
              }
              else{
                g_hour += 1;
              }
            }
            else{
              g_minute += 1;
            }
          }
          else{
            g_second += 1;
          }

          // 显示时间
          /*
          Serial.print(g_hour);
          Serial.print(":");
          Serial.println(g_minute);
          Serial.print(":");
          Serial.println(g_second);
          */
          
          lastNtpUpdate = nowTime;
        }
        vTaskDelay(200);
    }
    Serial.println("Ending taskTime");
    vTaskDelete( NULL );
 
}
